

#include "task.h"

void TaskItem::Release()
{
    delete this;
}

TaskItem::TaskItem( ITask* task )
    :task_(task_)
    ,next_taskitem_(NULL)
{

}

TaskItem::~TaskItem()
{
    if (task_!=NULL)
    {
        task_->Release();
    }
    task_=NULL;
}

TaskQueue::TaskQueue()
    :queue_head_(NULL)
    ,queue_tail_(NULL)
{
    InitializeCriticalSectionAndSpinCount(&critical_section_,4000);
    event_=CreateEvent(NULL,FALSE,TRUE,NULL);
}

TaskQueue::~TaskQueue()
{
    TaskItem *item;
    while (queue_head_!=NULL)
    {
        item=queue_head_;
        item->Release();
        queue_head_=queue_head_->next_taskitem_;
    }
    DeleteCriticalSection(&critical_section_);
    if (event_!=NULL)
    {
        CloseHandle(event_);
        event_=NULL;
    }
}

void TaskQueue::PushItem( TaskItem* item )
{
    item->next_taskitem_=NULL;
    EnterCriticalSection(&critical_section_);

    if (NULL!=queue_tail_)
    {
        queue_tail_->next_taskitem_=item;
        queue_tail_=item;
    }
    else
    {
        queue_head_=queue_tail_=item;
        SetEvent(event_);
    }
    
    LeaveCriticalSection(&critical_section_);
}

TaskItem* TaskQueue::PopItem()
{
    TaskItem*  item=NULL;

    while (NULL==item)
    {
        EnterCriticalSection(&critical_section_);

        if (queue_head_)
        {
            item=queue_head_;
            queue_head_=queue_head_->next_taskitem_;
            if (item==queue_tail_)
            {
                queue_tail_=NULL;
            }
        }

        LeaveCriticalSection(&critical_section_);

        if (NULL!=item)
        {
            return item;
        }

        WaitForSingleObject(event_,2000);
    }

    return item;
}
